const scale = require("../ble/scale.js")
const { uploadScaleData, prepareData } = require("../store/measureStore.js")
const Report = require('../report/Report')
const deepReportTransition = require('../utils/deepReportTransition')
const moment = require('../libs/moment')
const { appType } = require('../theme.config.js')
const { formatBirthday, toast, bitValue, kgTolb, unitValueConver } = require('../assets/js/common.js')
const { encryptStr } = require('../assets/js/encryptParams.js')
const http = require('../utils/http.js')
const formatItemData = require('../assets/js/formatItemData.js')
const $log = require('../utils/log.js')
const { anomaly, macRepair } = require('../utils/anomaly.js')
const { logUpload } = require('../utils/logUpload.js') 
const wsp = require('./wspMeasure.js')

let main = {}

/* console.log(encryptStr({
  weight: 50.75,
  mac: '',//'00:51:00:D3:02:23',
  resistance: 547,
  resistance500: 533,
  left_weight: 0,
  heart: 0
})) */

/* console.log('anomaly', anomaly({
  mac: 'A4:C1:38:CA:CE:C2',
  scale_weight: 0.01
})) */

module.exports = {
  unitValueConver,
  formatItemData,
  start() {},
  stop() {},
  restart() {},
  createConnect() {},
  stopDiscovery() {},
  init(data = {}, callback = () => {}) {
    console.log("init传入参数", data)
    let { appid, secret, birthday, gender, height, version, person_body_shape, person_goal, auto_connect, tipToast, calc_type, reset_device_list, muscle_rate_report, broadcast_timer, broadcast_timeout, use_broadcast_restart, use_scale_unit, use_restart, flag,
    bfw_report,
    mineral_salt_report,
    stand_weight_report,
    weight_control_report,
    fat_control_report,
    muscle_control_report,
    } = data     
    let bodyParams = {
      person_body_shape,
      person_goal,
      birthday,
      gender,
      height
    }
    let verifyStatus = true
    let _scale = null

    if (auto_connect == undefined) {
      auto_connect = true
    }

    if (use_restart == undefined) {
      use_restart = true
    }

    if (use_broadcast_restart == undefined) {
      use_broadcast_restart = true
    }

    if (!broadcast_timer) {//测量完，广播秤重连接时间
      broadcast_timer = 5000
    }
    if (!broadcast_timeout) {//没在测量的情况下，广播秤断开时间
      broadcast_timeout = 8000
    }

    data.auto_connect = auto_connect

    this.listen(callback)
    if (!flag) {
      if (height == undefined || gender == undefined || birthday == undefined) {
        main.callback({
          code: 1001,
          msg: "用户参数不完整"
        })
        verifyStatus = false
      } else if (!appid || !secret) {
        main.callback({
          code: 1016,
          msg: "请输入appid/secret"
        })
        verifyStatus = false
      } else if (gender != 0 && gender != 1) {
        main.callback({
          code: 1013,
          msg: "性别输入错误，只能传0或1",
        })
        verifyStatus = false
      } else if (height < 80 || height > 240) {
        main.callback({
          code: 1014,
          msg: "身高输入错误，只能传[80~240]",
        })
        verifyStatus = false
      } else if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(birthday)) {
        main.callback({
          code: 1015,
          msg: "生日输入错误，参考格式1990-01-01",
        })
        verifyStatus = false
      } else {
        let _birthday = birthday.split("-")
        _birthday[1] -= 1
        let diffYear = moment().diff(_birthday, "year")

        if (diffYear < 4 || diffYear > 80) {
          main.callback({
            code: 1015,
            msg: "生日输入错误，只支持4-80周岁",
          })
          verifyStatus = false
        }

      }
      data.birthday = formatBirthday(data.birthday)

    }

    if (!verifyStatus) {
      
      this.start = () => { }
      /*  openAdapter() { },
      closeAdapter() { },
      startDiscovery() { },*/
      this.stopDiscovery = () => { }
      this.restart = () => { }
      this.stop = () => { }
      this.createConnect = () => { }

      return
    }

    let _self = this
    let _available = false
    let _discovering = false
    let _connected = false
    let btnRestartStatus = false
    let touchStopDiscovery = false //是否手动触发停止扫描

    let measureFinishCallback = () => { }

    let boradcastUpStatus = false
    let boradcastTimer = null
    let broadcastTimeout = (time = broadcast_timeout) => {
      clearTimeout(boradcastTimer)
      boradcastTimer = setTimeout(() => {        
        !touchStopDiscovery && _scale && _scale.restart()
        boradcastUpStatus = false
      }, time)
    }
    let log = {
      debug() { }
    }
    if (data.log) {
      log = data.log({ level: 1 })
    }
    // console.log('log:', log)
    data.userAge = moment().diff(data.birthday, 'year')
    _scale = new scale({
      ...data,
      onAdapterStateChange(available, discovering) {
        _available = available
        _discovering = discovering

        if (!available) {
          toast("蓝牙未开启")
          main.callback({
            code: 1003,
            msg: "蓝牙未开启",
            bleState: "蓝牙未开启",
            state: "paused"
          })
        } else {
          if (_discovering && !_scale.device) {
            main.callback({
              code: 1005,
              msg: "请赤脚轻踩上秤",
              bleState: "请赤脚轻踩上秤",
              state: "paused"
            })
          } else if (!_discovering && !_scale.device) {
            
            //if (auto_connect && !btnRestartStatus) {
            //if (!auto_connect || (auto_connect && !btnRestartStatus)) {
            if (!btnRestartStatus) {
              _scale.startScan()
            } else {
              main.callback({
                code: 1004,
                msg: "空闲",
                bleState: "空闲",
                state: "paused"
              })
            }
          }
        }

      },
      onDeviceScan(devices) {

        if (auto_connect) {
          _scale.createConnect()
        } else {
          main.callback({
            code: 1030,
            msg: "已扫描到设备",
            bleState: "已扫描到设备",
            state: "paused",
            devices
          })
        }
      },
      onConnectStateChange(deviceId, connected) {
        _connected = connected

        if (_available) {
          if (!connected) {
            if (_discovering) {
              main.callback({
                code: 1005,
                msg: "请赤脚轻踩上秤",
                bleState: "请赤脚轻踩上秤",
                state: "paused"
              })
            } else {
              $log.clear()//清除日志

              main.callback({
                code: 1007,
                msg: "连接已断开",
                bleState: "连接已断开",
                state: "paused"
              })
            }
          } else if (!_scale.connecting) {
            /* main.callback({
              code: 1008,
              msg: "连接成功",
              bleState: "连接成功",
              state: "running"
            }) */
          }
        }
      },
      onToBeConnect() {
        main.callback({
          code: 1006,
          msg: "正在连接",
          bleState: "正在连接"
        })
      },
      onConnectSuccess() {
        wsp.wspMeasureFinish = false
        main.callback({
          code: 1008,
          msg: "连接成功",
          bleState: "连接成功",
          state: "running"
        })
      },
      onWeight(weight, unit = 'kg', unitType = 0) {
        let result = {
          code: 1009,
          msg: "正在测量",
          bleState: "正在测量",
          state: "running",
          realTimeWeight: weight,
          unit,
          unitType
        }
        main.callback(result)
      },
      onStartFetch(weight, unit = 'kg', unitType = 0) {
        main.callback({
          code: 1009,
          msg: "计算体质数据",
          bleState: "计算体质数据",
          realTimeWeight: weight,
          unit,
          unitType
        })
      },
      onWspMeasure(data) {
        wsp.wspMeasure(data, _scale)
      },
      onWspMeasureEnd(wspData, unit = 'kg', unitType = 0) {
        wspData.birthday = data.birthday
        wspData.gender = data.gender
        wspData.height = data.height
        Object.assign(wspData, {
          bmr_flag: 1,
          water_flag: 1,
          protein_flag: 1,
          bodyage_flag: 1,
          body_shape_flag: 1,
          bone_flag: 1,
          muscle_flag: 1,
          subfat_flag: 1,
          fat_free_weight_flag: 1,
          visfat_flag: 1,
          sinew_flag: 1,
        })
        let impedance = _scale.impedanceBroadcast(wspData.resistance, wspData.second_resistance)
        let callbackData = {
          code: 1010,
          msg: "测量完成",
          bleState: "测量完成",
          state: "paused",
          result: prepareData(wspData, {
            muscle_rate_report,
            bfw_report,
            mineral_salt_report,
            stand_weight_report,
            weight_control_report,
            fat_control_report,
            muscle_control_report,
          }),
          unit,
          unitType,
          impedance
        }
        main.callback(callbackData)
      },
      onStartRequest(weight) {
        main.callback({
          code: 1020,
          msg: "数据上传中",
          bleState: "数据上传中",
          realTimeWeight: weight
        })
      },
      onSteadyData({ scaleParam, impedance, returnStatus = false, isBroadcast = false, unit = 'kg', unitType = 0 }) {
        //上传测量数据
        if (flag) {
          log.debug('scaleParam', scaleParam)
          log.debug('_scale.deviceInfo', _scale.deviceInfo)
          log.debug('_scale.device', _scale.device)
          log.debug('_scale.mac', _scale.mac)
          $log.writeBody('scaleParam', scaleParam)
          $log.writeBody('_scale.deviceInfo', _scale.deviceInfo)
          $log.writeBody('_scale.device', _scale.device)
          $log.writeBody('_scale.mac', _scale.mac)
          
          let encryptStrResult = encryptStr({
            weight: scaleParam.scale_weight,
            mac: macRepair(_scale.deviceInfo.mac, _scale.mac),
            resistance: scaleParam.scale_resistance,
            resistance500: scaleParam.scale_resistance500,
            left_weight: scaleParam.left_weight || 0,
            heart: scaleParam.heart_rate
          }).str
          
          log.debug('encryptResult', encryptStrResult)
          $log.writeBody('encryptResult', encryptStrResult)

          if (returnStatus) {
            _self.onRequest({
              hexString: encryptStrResult,
              inquiry: true
            })
          } else {
            if (anomaly(_scale.deviceInfo.mac, _scale.mac)) {
              //平安日志屏蔽
              /* logUpload({
                platform: 'xcx_plugin',
                log_info: $log.result()
              }).then(() => {
                $log.clearBody()
              }) */
              $log.clearBody()
            }
            _self.onRequest({
              hexString: encryptStrResult
            })
          }
          
          _self.requestEnd = (data) => {
            if (data.inquiry) {
              delete data.inquiry
              _scale.outRequestEnd(data)
            } else {
              let callbackData = {
                code: 1010,
                msg: "测量完成",
                bleState: "测量完成",
                state: "paused",
                result: data,
                unit,
                unitType,
              }
              main.callback(callbackData)
            }

          }
          measureFinishCallback && measureFinishCallback()
          return Promise.resolve()
        }
        return uploadScaleData({ device: _scale.deviceInfo, scaleParam, bodyParams, APP_ID: appid, version, calc_type }).then(res => {
          if (returnStatus) {
            return res
          }
          
          measureFinishCallback && measureFinishCallback()

          let result = prepareData(res, { 
            muscle_rate_report,
            bfw_report,
            mineral_salt_report,
            stand_weight_report,
            weight_control_report,
            fat_control_report,
            muscle_control_report,
          })
          let callbackData = {
            code: 1010,
            msg: "测量完成",
            bleState: "测量完成",
            state: "paused",
            result,
            unit,
            unitType,
            impedance
          }

          if (isBroadcast) {
            callbackData.result = unitValueConver(result, unit)
          }
          main.callback(callbackData)
        }).catch(err => {
          let { code, msg } = err

          if (code == 400) {
            main.callback({
              code: 400,
              msg: msg
            })
          } else {
            main.callback({
              code: -1,
              msg: "请求失败",
              err
            })
          }
        })
      },
      onBroadcastScale: device => {
        let data = device.advertisArrayData

        _scale.that.broadcastBatch({
          device,
          status: data[8],
          w_l: data[9],
          w_h: data[10],
          model_l: data[15],
          model_h: data[16],
          r_l: data[11],
          r_h: data[12]
        })
      },
      onOneToOne: (device) => {
        let _self = _scale
        let data = device.advertisArrayData
        let status = data[17]
        let count = data[24].toString(16) + data[25].toString(16)

        if ((status >> 0) & 1) {
          // console.log('broadcastCount', _self.broadcastCount)
          if (_self.broadcastCount == count) {
            broadcastTimeout()
            return
          }
        }

        let resistance = 0
        let weightScaleFlag = false //体重秤标识

        if (!((status >> 4) & 1)) {//如果是体脂秤
          if ((status >> 5) & 1) {//测量到阻抗的情况下，生成随机阻抗值
            resistance = 480 + Math.round(Math.random() * 40)//随机一个480到520左右的阻抗值
          }
        } else {
          weightScaleFlag = true
        }

        _self.that.broadcastBatch({
          delay: 8000,//一对一加长时间延时处理回调
          weightScaleFlag,
          device,
          status,
          w_l: data[19],
          w_h: data[20],
          r_val: resistance,
          model_l: data[22],
          model_h: data[23],
          callback: () => {
            // console.log('count', count)
            _self.broadcastCount = count
          }
        })
      },
      broadcastBatch: ({ delay = 0, weightScaleFlag = false, device, status, r_val = 0, w_l, w_h, model_l, model_h, r_l, r_h, callback = () => { } }) => {
        if (boradcastUpStatus) return
        let _self = _scale
        let data = device.advertisArrayData
        let weightVal = _self.decodeWeight(w_h, w_l)
        let realWeightVal = weightVal
        let unit = 'kg'
        let unitType = 0

        if (use_scale_unit) {
          let b2 = bitValue(status, 2)//status >> 2 & 1
          let b1 = bitValue(status, 1)//status >> 1 & 1

          if (b2 === 1 && b1 === 1) { //6,7 斤
            weightVal *= 2
            unit = '斤'
            unitType = 1
          } else if (b2 === 1 && b1 === 0) { //磅lb
            weightVal = kgTolb(weightVal)
            unit = 'lb'
            unitType = 2
          }
        }

        broadcastTimeout()

        _self.that.onWeight(weightVal, unit, unitType)

        if ((status >> 0) & 1) {
          if (realWeightVal) {
            boradcastUpStatus = true
          }
          clearTimeout(boradcastTimer)

          //测量完成的回调
          measureFinishCallback = () => {
            if (use_broadcast_restart) {
              let timer = broadcast_timer

              if (delay && delay > broadcast_timer) {
                timer = delay
              }
              broadcastTimeout(timer)
            } else {
              _scale.stopDiscovery()
            }
            measureFinishCallback = () => { }
          }

          let resistance = 0

          if (r_val) {
            resistance = r_val
          } else if (r_h && r_l) {
            resistance = _self.decodeImpedance(r_h, r_l)
          }

          let manufacturer = _self.arrayToHexString([model_h]) + _self.arrayToHexString([model_l])
          const hasResistance = resistance > 0 ? true : false
          let impedance = _scale.impedanceBroadcast(resistance, resistance)

          _self.that.onStartFetch(weightVal, unit, unitType)

          if (realWeightVal) {
            _self.that.onSteadyData({
              isBroadcast: true,
              unit,
              unitType,
              scaleParam: {
                mac: _self.deviceInfo.mac,
                scale_weight: realWeightVal,
                scale_resistance: resistance,
                scale_resistance500: resistance,
                heart_rate: 0,
                manufacturer,
                app_type: appType,
              },
              impedance,
              hasResistance
            })
          }
          callback && callback()
        }
      },
      onError(err) {
        let { errCode, errMsg } = err
        console.log("onError", err)

        if (errCode == 10001) {
          main.callback({
            code: 1003,
            msg: "蓝牙未开启",
            bleState: "蓝牙未开启",
            state: "paused"
          })
        } else if (errCode == 10003) {
          main.callback({
            code: 10003,
            msg: "微信蓝牙api连接失败",
            bleState: "蓝牙连接失败",
            state: "paused",
            err
          })
        } else {
          main.callback({
            code: errCode,
            msg: errMsg,
            err
          })
        }
      }
    })

    
    this.start = () => {
      $log.clear()
      touchStopDiscovery = false
      return _scale.startScan.bind(_scale)()
    }
      /* openAdapter: _scale.openAdapter.bind(_scale),
      closeAdapter: _scale.closeAdapter.bind(_scale),
      startDiscovery: _scale.startDiscovery.bind(_scale),*/
    this.stopDiscovery = () => {
      btnRestartStatus = true
      touchStopDiscovery = true

      return _scale.stopDiscovery.bind(_scale)().then((res) => {
        setTimeout(() => {
          btnRestartStatus = false
        }, 300)
        return res
      })
    }
    this.restart = () => {
      /* if (tipToast !== false) {
        toast("请上秤")
      } */
      touchStopDiscovery = false
      btnRestartStatus = true
      if (reset_device_list && !auto_connect) {
        _scale.deviceObj = {}
      }
      $log.clear()
      return _scale.restart.bind(_scale)().then(() => {
        setTimeout(() => {
          btnRestartStatus = false
        }, 300)
      })
    }    
    this.stop = _scale.closeConnect.bind(_scale)
    this.createConnect = _scale.createConnect.bind(_scale)
    
  },
  listen(callback = () => {}) {
    if (typeof callback == "function") {
      main.callback = callback
    }
  },
  deepReport(obj = {}) {
    if (!obj.bodyfat || !obj.protein || !obj.bmr || !obj.bodyAge || !obj.bone || !obj.muscle) {
      console.log('deepReport 深度报告缺少参数')
      return {}
    }
    let result = deepReportTransition(obj)
    
    return result
  },
  reportData(obj = {}, params = {}) {
    let reportData = {}
    let { unit } = params

    if (Object.keys(params).length) {
      console.log('reportData传入参数:', obj, params)
    } else {
      console.log('reportData传入参数:', obj)
    }

    if (!obj.origin) {
      for (let key in obj) {
        if (key != "birthday") {
          let num = parseFloat(obj[key])
          if (isNaN(num)) {
            delete obj[key]
          } else {
            obj[key] = num
          }
        }
      }
      obj.origin = {
        bmr_flag: 1,
        water_flag: 1,
        protein_flag: 1,
        bodyage_flag: 1,
        body_shape_flag: 1,
        bone_flag: 1,
        muscle_flag: 1,
        subfat_flag: 1,
        fat_free_weight_flag: 1,
        visfat_flag: 1,
        sinew_flag: 1,
      }
    }
    if (obj.weight == undefined || obj.bmi == undefined || obj.birthday == undefined) {
      reportData.code = 2001
      reportData.msg = "缺少参数"
    } else if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(obj.birthday)) {
      reportData.code = 2002
      reportData.msg = "birthday格式不正确(1990-01-01)"
    } else {
      reportData = new Report(obj, params)
      reportData.code = 2000
      reportData.msg = ""
      delete reportData.measure.origin
      if (unit && typeof unit == 'string') {
        unit = unit.trim()
        if (unit != 'kg') {
          reportData = unitValueConver(reportData, unit)
        }
      }
    }
    return Promise.resolve(reportData)
  },
}